﻿gomoku = function () {
    //$.connection.hub.url = 'http://localhost:18392/echannel/hubs';

    var hub = $.connection.gomoku;

    hub.notifyPlayersStatus = function (pList) {
        var $pls = $('#players');
        $pls.html('');
        for (var i = 0; i < pList.length; i++) {
            var p = pList[i];
            var name = p.Name == undefined || p.Name == '' ? 'Anynomous' : p.Name;
            $pls.append('<li data-ClientContextId="{ClientContextId}">'.replace("{ClientContextId}", p.ClientContextId) + name + '</li>');
        }

        $pls.children('li').dblclick(function () {
            var vsId = $(this).attr('data-ClientContextId');
            if (vsId == clientId)
                return;

            hub.requestMatch(vsId);
            $('#matchStatus').html('Math: Waiting');
        });
    };

    var invitingPlayer = undefined;
    var clientId = undefined;

    var gomokuDrawer = new GomokuDrawer({
        container: 'gomokuDrawContainer',
        onItemAdded: function (item) {
            sendingItem = item;
            changeTurn(false);
            hub.tick({ X: item.x, Y: item.y }, currentMatch.Id);
        },
        invalidMove: function (txt) {
            showError(txt);
        }
    });

    function showError(txt) {
        var $error = $('#errorMessage');
        $error.html(txt);
        $error.css('visibility', 'visible');
        $error.fadeIn(500);
        $error.fadeOut(2000);
    }


    hub.onMatchRequest = function (player) {
        invitingPlayer = player;
        var name = player.Name == undefined || player.Name == '' ? 'Anynomous' : player.Name;
        var txt = 'Player ' + name + ' is inviting you to a match. Do you accept?';
        $('#matchRequestText').html(txt);

        $('#matchConfirm').css('visibility', 'visible');
    };
    hub.onReceiveId = function (id) {
        clientId = id;
    };

    $('#btnYesMatch').click(function () {
        $('#matchConfirm').css('visibility', 'hidden');
        hub.answerMatch(invitingPlayer.ClientContextId, 'yes');

    });

    $('#btnNoMatch').click(function () {
        $('#matchConfirm').css('visibility', 'hidden');
        hub.answerMatch(invitingPlayer.ClientContextId, 'no');
    });

    var currentMatch = undefined;

    hub.onMatchAnswered = function (match, result) {
        if (result != 'yes') {
            $('#matchStatus').html('Match: No');
            return;
        }

        currentMatch = match;
        changeTurn(clientId == match.Player1.ClientContextId);
        gomokuDrawer.match = currentMatch;

        gomokuDrawer.setIsEvent(clientId == match.Player1.ClientContextId);
        gomokuDrawer.setMatchName('Match: ' + currentMatch.Player1.Name + " vs " + currentMatch.Player2.Name);

        gomokuDrawer.draw();
    };

    function changeTurn(isMine) {
        gomokuDrawer.isMyTurn = isMine;
        
        
        $('#turnIndicator').removeClass("Mine His");
        if (isMine) {
            $('#turnIndicator').addClass('Mine');
        } else {
            $('#turnIndicator').addClass('His');
        }
    }

    $('#btnSetPlayerName').click(function () {
        setPlayerName();
    });

    function setPlayerName() {
        hub.setPlayerName($('#playerName').val()).fail(function (evt) {
            showError(evt);
        });
    }
    $('#playerName').keypress(function (e) {
        var code = (e.keyCode ? e.keyCode : e.which);
        if (code == 13) { //Enter keycode
            setPlayerName();
        }
    });

    $('#testTick').click(function () {
        hub.tick({ X: 0, Y: 0 }, currentMatch.Id);
    });

    $.connection.hub.start().fail(function (evt) {
        throw "Fail:" + evt;
    });
    var sendingItem = undefined;



    hub.notifyTick = function (cell) {
        if (sendingItem != undefined) {
            gomokuDrawer.isMyTurn = false;
            sendingItem.setIsAdding(false);
            sendingItem = undefined;
        } else {
            var viewModel = new ItemViewModel({ x: cell.X, y: cell.Y, mine: cell.Player.ClientContextId == clientId });
            changeTurn(!viewModel.mine);

            if (viewModel.mine)
                viewModel.isEvent = gomokuDrawer.getIsEvent();
            else
                viewModel.isEvent = !gomokuDrawer.getIsEvent();

            viewModel.setIsAdding(false);
            gomokuDrawer.addItem(viewModel);
        }

        gomokuDrawer.draw();
    };

    hub.notifyOver = function (winner) {
        gomokuDrawer.notifyOver(winner == clientId);
    };
};



ItemViewModel = function (opts) {
    this.x = opts.x;
    this.y = opts.y;
    this.mine = opts.mine;
    this.id = undefined;
    var isAdding = false;
    var uipath = undefined;
    this.getUiPath = function () {
        if (uipath == undefined) {
            uipath = new Kinetic.Path({
                fill: "gray",
                stroke: "transparent"
            });

            uipath.ViewModel = this;
        }

        return uipath;
    };
    this.setIsAdding = function (val) {
        isAdding = val;
        if (isAdding)
            this.getUiPath().attrs.alpha = 0.5;
        else
            this.getUiPath().attrs.alpha = 1;
    };

    this.getIsAdding = function () {
        return isAdding;
    };
    this.isEvent = opts.isEvent == undefined ? false : opts.isEvent;
};

GomokuDrawer = function (options) {
    var $container = $('#' + options.container);
    var cW = $container.width();
    var cH = $container.height();
    var cellSize = 40;
    var startI = 500;
    var crossSign = 'F1 M 31.5988,33.2656C 28.5798,31.4861 25.5607,29.7065 23.269,28.0815C 20.9774,26.4565 19.4132,24.9861 17.8489,23.5156L 9.97394,32.6458C 9.97394,32.6458 7.55725,34.0625 5.76559,32.6041C 3.97394,31.1458 5.76559,28.1875 5.76559,28.1875L 14.2864,19.5156L 6.07809,9.28125C 6.07809,9.28125 5.20309,7.21875 6.73434,5.96875C 8.26559,4.71875 9.98434,5.71875 9.98434,5.71875L 18.1614,16.0781L 27,7.18225C 27,7.18225 28.1302,6.43225 29.0833,7.26038C 30.0364,8.0885 29.625,9.18225 29.625,9.18225L 20.8489,19.7291C 22.2309,21.7465 23.6128,23.7638 25.4045,26.0199C 27.1961,28.276 29.3975,30.7709 31.5988,33.2656 Z';
    var circleSign = 'F1 M 18.5,21.3021L 17.3125,24.3229C 17.3124,24.3229 25.6178,29.0656 30.9375,20.6979C 34.7916,14.6354 30.2855,4.13324 20.3541,4.80206C 10.1458,5.48956 5.8541,9.92706 5.24994,17.8021C 4.46564,28.0251 10.2916,33.2396 17.9999,34.3021C 27.8675,35.6622 33.8749,27.5521 33.8749,27.5521L 32.7499,24.9271C 32.7499,24.9271 28.4363,31.563 18.1666,30.3437C 10.2708,29.4062 8.90771,21.3832 9.29163,18.5312C 9.72913,15.2812 10.9791,8.46869 20.3125,7.94788C 26.7819,7.58685 30.6875,14.8646 28.7291,18.9896C 25.8928,24.964 18.6249,21.4271 18.5,21.3021 Z ';

    var stage = new Kinetic.Stage({
        container: options.container,
        width: cW,
        height: cH
    });
    var layer = new Kinetic.Layer();
    stage.add(layer);

    var axisGroup = new Kinetic.Group();
    this.match = undefined;

    var layerCanvas = $(layer.canvas);
    var rect = {
        x1: 5, y1: 5,
        x2: layerCanvas.width() - 5, y2: 5,
        x3: layerCanvas.width() - 5, y3: layerCanvas.height() - 5,
        x4: 5, y4: layerCanvas.height() - 5
    };

    var matchText = new Kinetic.Text({
        x: 10,
        y: 10,
        text: "Match: NONE",
        fontSize: 10,
        textFill: "green"
    });
    this.isMyTurn = true;


    var overText = new Kinetic.Text({
        x: cW / 2 - 100,
        y: cH / 2 - 20,
        stroke: '#555',
        strokeWidth: 5,
        fill: '#ddd',
        text: 'You win!',
        fontSize: 16,
        fontFamily: 'Calibri',
        fontStyle: 'bold',
        textFill: 'green',
        width: 200,
        padding: 20,
        align: 'center',
        shadow: {
            color: 'black',
            blur: 1,
            offset: [10, 10],
            alpha: 0.2
        },
        alpha: 0
    });


    layer.add(matchText);
    layer.add(overText);
    overText.setZIndex(100);

    this.setMatchName = function (name) {
        matchText.setText(name);
    };


    this.notifyOver = function (winnerIsYou) {
        if (winnerIsYou) {
            overText.setText('You win!');
            overText.attrs.textFill = 'green';
        } else {
            overText.setText('You loose!');
            overText.attrs.textFill = 'red';
        }
        overText.attrs.alpha = 1;
    };

    var me = this;

    var cursorItem = new ItemViewModel({ x: startI, y: startI, mine: true });
    cursorItem.getUiPath().attrs.alpha = 0;

    calculateItemPath(cursorItem);

    layer.add(cursorItem.getUiPath());

    $(layer.parent.content).mousemove(function (evt) {
        var mpos = { x: evt.offsetX, y: evt.offsetY };

        cursorItem.x = startI + Math.floor(mpos.x / cellSize);
        cursorItem.y = startI + Math.floor(mpos.y / cellSize);
        calculateItemPath(cursorItem);
        cursorItem.getUiPath().attrs.alpha = 0.5;

        layer.draw();
    });
    $(layer.parent.content).mouseleave(function(evt) {
        cursorItem.getUiPath().attrs.alpha = 0;
        layer.draw();
    });


    this.setIsEvent = function (isEvent) {
        cursorItem.isEvent = isEvent;
    };
    this.getIsEvent = function () {
        return cursorItem.isEvent;
    };

    $(layer.parent.content).click(function (evt) {
        if(me.match == undefined) {
            options.invalidMove("No match! Invite someone to play");
            return;
        }
        if (!me.isMyTurn) {
            options.invalidMove("Not your turn");
            return;
        }


        var item = new ItemViewModel({ x: cursorItem.x, y: cursorItem.y, mine: cursorItem.mine, isEvent: cursorItem.isEvent });

        var chk = items.singleOrDefault(function (i) {
            return i.x == item.x && i.y == item.y;
        });

        if (chk != undefined) {
            options.invalidMove("Invalid move");
            return;
        }


        item.setIsAdding(true);
        me.addItem(item);

        if (options.onItemAdded) {
            options.onItemAdded(item);
        }
    });

    var items = [];

    this.addItem = function (item) {
        calculateItemPath(item);
        layer.add(item.getUiPath());
        items.push(item);

        me.isMyTurn = !item.mine;
    };

    this.updateItem = function (item) {
        var i = layer.children.single(function (it) {
            return it.ViewModel == item;
        });

        i.ViewModel.setIsAdding(item.getIsAdding());
    };

    function calculateItemPath(item) {

        var deltaVal = { x: item.x - startI, y: item.y - startI };
        var pos = { x: deltaVal.x * cellSize + 5, y: deltaVal.y * cellSize + 5 };
        item.getUiPath().attrs.x = pos.x;
        item.getUiPath().attrs.y = pos.y;

        if (item.isEvent) {
            item.getUiPath().setData(crossSign);
            item.getUiPath().attrs.fill = 'red';
        } else {
            item.getUiPath().setData(circleSign);
            item.getUiPath().attrs.fill = 'green';
        }

    }


    function sp(x, y, t) {
        if (t == undefined)
            t = 'L';
        return t + x + ',' + y;
    }


    function makeAxis() {
        if (!layer.children.contains(axisGroup)) {
            layer.add(axisGroup);
            axisGroup.setZIndex(0);
        }
        axisGroup.removeChildren();

        var x = cellSize + rect.x1;
        var valX = startI;
        while (x < rect.x2) {
            var line = new Kinetic.Line({
                points: [x, rect.y1, x, rect.y3],
                stroke: "#E8E8E8",
                strokeWidth: 1,
                valIndex: valX
            });

            axisGroup.add(line);

            x += cellSize;
            valX++;
        }

        var y = cellSize + rect.y1;
        var valY = startI;
        while (y < rect.y3) {
            var line = new Kinetic.Line({
                points: [rect.x1, y, rect.x2, y],
                stroke: "#E8E8E8",
                strokeWidth: 1,
                valIndex: valY
            });

            axisGroup.add(line);

            y += cellSize;
            valY++;
        }
    }

    this.draw = function () {
        layer.draw();
    };


    makeAxis();

    this.draw();
};